﻿using System;
using BP.DA;
using BP.En;
using System.Data;
using BP.Difference;

namespace BP.Demo
{
    /// <summary>
    /// 推断 属性
    /// </summary>
    public class StockAttr : EntityNoNameAttr
    {
        /// <summary>
        /// 推断内容
        /// </summary>
        public const string Docs = "Docs";
    }
    /// <summary>
    /// 推断
    /// </summary>
    public class Stock : EntityNoName
    {
        #region 构造方法
        /// <summary>
        /// 权限控制
        /// </summary>
        public override UAC HisUAC
        {
            get
            {
                UAC uac = new UAC();
                uac.IsUpdate = true;
                uac.IsInsert = true;
                return uac;
            }
        }
        /// <summary>
        /// 推断
        /// </summary>
        public Stock()
        {
        }
        public Stock(string no)
        {
            SetValByKey(EntityNoNameAttr.No, no);
            Retrieve();
        }
        /// <summary>
        /// 重写基类方法
        /// </summary>
        public override Map EnMap
        {
            get
            {
                if (_enMap != null)
                    return _enMap;

                Map map = new Map("Demo_Stock", "推断");

                map.AddGroupAttr("基本信息");
                map.AddTBStringPK("No", null, "编号", true, true, 1, 59, 100);
                map.AddTBString("Name", null, "名称", true, true, 0, 300, 100);

                map.AddGroupAttr("当日价格");//当日价格.
                map.AddTBString("DT", null, "日期", true, false, 0, 100, 10, true); //日期:2025-09-09
                map.AddTBMoney("OpenNum", 0, "开盘价", true, true);
                map.AddTBMoney("MaxNum", 0, "最高", true, true);
                map.AddTBMoney("MinNum", 0, "最低", true, true);
                map.AddTBMoney("SwingNum", 0, "振幅", true, true);
                map.AddTBMoney("CloseNum", 0, "收盘价", true, true);


                map.AddGroupAttr("预测方式");
                map.AddDDLSysEnum("ExceModel", 0, "模式", true, true, "ExceModel", "@0=单股@1=多线程");
                map.AddTBMoney("Principal", 20, "本金", true, true);

                map.AddGroupAttr("单次推断参数");
                map.AddTBDate("DTFrom", null, "日期从", true, false);
                map.AddTBDate("DTTo", null, "日期到", true, false);
                map.AddTBInt("TradeTimes", 0, "交易次", true, true);//从原始数据自动计算.

                map.AddTBInt("CarWidth", 1, "车宽", true, true);
                map.AddTBInt("NearDays", 4, "最近的天数", true, true);

                map.AddGroupAttr("综合推断参数");
                map.AddTBInt("CarWidthMin", 2, "车宽Min", true, false);
                map.AddTBInt("CarWidthMax", 18, "车宽Max", true, false);
                map.AddTBInt("NearDaysMin", 2, "天数Min", true, false);
                map.AddTBInt("NearDaysMax", 10, "天数Max", true, false);

                map.AddGroupAttr("最优解");
                map.AddTBInt("RelCarWidth", 2, "车宽Min", true, true);
                map.AddTBInt("RelNearDays", 18, "车宽Max", true, true);
                map.AddTBMoney("RelWin", 20, "纯盈利", true, true);
                map.AddTBString("RptMyPK", null, "最优解主键", true, true, 0, 60, 150);

                map.AddGroupAttr("报告");
                map.AddTBStringDoc("JNote", null, "报告", true, true, true, 10);
                map.AddTBStringDoc("MyNote", null, "明日指导", true, true, true, 10);

                _enMap = map;
                return _enMap;
            }
        }
        #endregion

        /// <summary>
        /// 获得当前数据
        /// </summary>
        /// <returns></returns>
        public string DTS_CurrData()
        {
            DTS_Stock st = new DTS_Stock();
            string msg = st.GenerCurrData(this);
            return "执行成功" + msg;
        }

        /// <summary>
        /// 同步数据:历史数据.
        /// </summary>
        /// <returns></returns>
        public string DTS_Stock()
        {
            DTS_Stock st = new DTS_Stock();
            string msg = st.GenerHistoryData(this.No, "2025");
            return "执行成功" + msg;
        }
 
        public string DoGenerAll()
        {
            //this.ImpData(); //读取数据.
            //return "xxx";

            #region 准备数据.
            //DBAccess.RunSQL("UPDATE Demo_Trade SET No=Trim(No)"); //整理基础数据.
            //DBAccess.RunSQL("UPDATE Demo_Trade SET NO=REPLACE(NO,'/','-')"); //整理基础数据.
            //DBAccess.RunSQL("UPDATE Demo_Trade SET IsOK=0,StockNo='' "); //清除标记..
            //DBAccess.RunSQL("UPDATE Demo_Trade SET SwingNum = MaxNum - MinNum"); //振幅.
            //DBAccess.RunSQL("DELETE FROM Demo_RptDtl WHERE RptMyPK='" + this.MyPK + "'"); //清除历史记录.

            Trade td = new Trade();
            td.CheckPhysicsTable();

            Stock jd = new Stock();
            jd.CheckPhysicsTable();

            Rpt rpt = new Rpt();
            rpt.CheckPhysicsTable();

            RptDtl rptDtl = new RptDtl();
            rptDtl.CheckPhysicsTable();
            #endregion 准备数据.

            #region 1. 删除所有的样本
            //删除数据.
            string sql = "DELETE FROM Demo_RptDtl WHERE StockNo='" + No + "'";
            DBAccess.RunSQL(sql);
            sql = "DELETE FROM Demo_Rpt WHERE  StockNo='" + No + "' ";
            DBAccess.RunSQL(sql);
            #endregion 删除所有的样本

            #region 2. 遍历组合生成样本数.
            //生成所有的样本.
            int num = 0;
            bool isOuShuo = true; //偶数.
            for (int carWidth = CarWidthMin; carWidth < CarWidthMax; carWidth++)
            {
                if (isOuShuo == true)
                {
                    isOuShuo = false;
                }
                else
                {
                    isOuShuo = true;
                    continue;
                }

                for (int YangBen = NearDaysMin; YangBen < NearDaysMax; YangBen++)
                {
                    CarWidth = carWidth;
                    NearDays = YangBen;
                    Update();

                    //执行报告.
                    this.DoStockModel1();
                    num++;
                }
            }
            #endregion 2. 遍历组合生成样本数.

            #region 3. 求最优解.
            //求出来最高的盈利报告.
            sql = "SELECT MyPK,ResultWin FROM Demo_Rpt WHERE  StockNo = '" + No + "' ORDER BY ResultWin DESC LIMIT 1";
            string mypk = DBAccess.RunSQLReturnString(sql);
            Rpt RptMax = new Rpt(mypk);
            RelCarWidth = RptMax.CarWidth;
            RelNearDays = RptMax.NearDays;
            this.RptMyPK = RptMax.MyPK;
            #endregion  求最优解.

            #region 4. 求最差解..
            sql = "SELECT MyPK FROM Demo_Rpt WHERE StockNo = '" + No + "'  ORDER BY ResultWin LIMIT 1";
            mypk = DBAccess.RunSQLReturnString(sql);
            Rpt RptMin = new Rpt(mypk);
            #endregion  求最优解.

            string note = "报告";
            note += "\t\n 1. 参数:日期从" + DTFrom + ",到:" + DTTo + "，交易次数:" + TradeTimes;
            note += "\t\n 2. 参数:路宽范围：" + CarWidthMin + " - " + CarWidthMax + ", 样本天数范围:" + NearDaysMin + " - " + NearDaysMax;
            note += "\t\n 3. 共计生成报告[" + num + "]份，交易样本[" + num * TradeTimes + "]份。";
            note += "\t\n 4. 最高纯盈利值【" + RptMax.ResultWin + "】,收益率【" + RptMax.ResultWinRate + "】车宽【" + RptMax.CarWidth + "】,样本天【" + RptMax.NearDays + "】主键:【" + RptMax.MyPK + "】";
            note += "\t\n 5. 最差纯盈利值【" + RptMin.ResultWin + "】,收益率【" + RptMax.ResultWinRate + "】车宽【" + RptMin.CarWidth + "】,样本天【" + RptMin.NearDays + "】主键:【" + RptMin.MyPK + "】";
            note += "\t\n     报告日期:" + DataType.CurrentDateTimess;

            JNote = note;
            Update();
            return note;
        }

        /// <summary>
        /// 按照平均数来预测
        /// </summary>
        /// <returns></returns>
        public string DoStockModel1()
        {
            string sql = "SELECT count(*) as No FROM Demo_Trade WHERE (Name >='" + this.DTFrom + "' AND Name <='" + this.DTTo + "') AND StockNo='" + this.No + "' ORDER BY No ";
            TradeTimes = DBAccess.RunSQLReturnValInt(sql);
            if (TradeTimes == 0) return "err@请检查日期是否错误:从：[" + this.DTFrom + "] 到:[" + this.DTTo + "], SQL:" + sql;

            Rpt rpt = new Rpt();
            rpt.Copy(this);
            rpt.MyPK = DBAccess.GenerGUID();
            rpt.IdxNo = DBAccess.GenerOID("Stock").ToString();
            rpt.StockNo = No;
            rpt.StockName = Name;
            rpt.StockNo = No; //股票编号.
            rpt.ResultAll = ResultAll;
            rpt.ResultTop = ResultTop;
            rpt.ResultDown = ResultDown;
            rpt.DTFrom = this.DTFrom;
            rpt.DTTo = this.DTTo;
            rpt.TradeTimes = TradeTimes; //样本数据.
            rpt.Insert(); //插入一笔数据.

            //执行推断.
            string msg = rpt.DoStockModel1();
            return msg;
        }

        /// <summary>
        /// 预测明日的数据
        /// </summary>
        /// <returns></returns>
        public string GenerStockByRelData()
        {
            if (DataType.IsNullOrEmpty(RptMyPK) == true)
                return "err@没有生成最优解，无法执行预测。";

            Rpt rpt = new Rpt();
            rpt.MyPK = RptMyPK;
            if (rpt.RetrieveFromDBSources() == 0)
                return "err@最优解数据已经删除，无法执行预测。";

            //获得范围数据.
            string sql = "SELECT No,Name FROM Demo_Trade WHERE StockNo='" + No + "' ORDER BY No DESC LIMIT " + this.RelNearDays;
            DataTable dataTable = DBAccess.RunSQLReturnTable(sql);
            if (dataTable.Rows.Count != this.RelNearDays) return "err@获取最近采集数据错误：" + sql;

            //获得最近的交易编号.
            string tradeNo = dataTable.Rows[0][0].ToString();
            string tradeName = dataTable.Rows[0][1].ToString();

            RptDtl dtl = new RptDtl();
            dtl.TradeNo = tradeNo;
            dtl.TradeName = tradeName;
            dtl.DoStockMode_Avg(rpt); //执行预测.

            string note = "按照最优解预测当前日期[" + dtl.TradeNo + "],预测下一日的数据如下:";
            note += "\t\n 1. 最优解参数车宽:" + rpt.CarWidth + ",样本天:" + rpt.NearDays;
            note += "\t\n 2. 最高值:" + dtl.StockMax + ",最低值:" + dtl.StockMin + ",中线:" + dtl.StockCenter + ",收盘价:" + dtl.StockCloseNum;
            note += "\t\n 3. 卖出值:" + dtl.StockSafeTop + ",购入值:" + dtl.StockSafeDown + ".";
            note += "\t\n    -- " + DataType.CurrentDateTime;

            MyNote = note;
            Update();

            return note;
        }

        #region 基本属性
        public decimal RelWin
        {
            get
            {
                return GetValDecimalByKey("RelWin");
            }
            set
            {
                SetValByKey("RelWin", value);
            }
        }
        public int RelNearDays
        {
            get
            {
                return GetValIntByKey("RelNearDays");
            }
            set
            {
                SetValByKey("RelNearDays", value);
            }
        }
        public decimal RelCarWidth
        {
            get
            {
                return GetValDecimalByKey("RelCarWidth");
            }
            set
            {
                SetValByKey("RelCarWidth", value);
            }
        }

        /// <summary>
        /// 最优解报告编号
        /// </summary>
        public string RptMyPK
        {
            get
            {
                return GetValStringByKey("RptMyPK");
            }
            set
            {
                SetValByKey("RptMyPK", value);
            }
        }
        public string MyNote
        {
            get
            {
                return GetValStringByKey("MyNote");
            }
            set
            {
                SetValByKey("MyNote", value);
            }
        }
        public string JNote
        {
            get
            {
                return GetValStringByKey("JNote");
            }
            set
            {
                SetValByKey("JNote", value);
            }
        }

        public int NearDaysMin
        {
            get
            {
                return GetValIntByKey("NearDaysMin");
            }
            set
            {
                SetValByKey("NearDaysMin", value);
            }
        }
        public int NearDaysMax
        {
            get
            {
                return GetValIntByKey("NearDaysMax");
            }
            set
            {
                SetValByKey("NearDaysMax", value);
            }
        }

        public int TradeTimes
        {
            get
            {
                return GetValIntByKey("TradeTimes");
            }
            set
            {
                SetValByKey("TradeTimes", value);
            }
        }
        public int CarWidthMin
        {
            get
            {
                return GetValIntByKey("CarWidthMin");
            }
            set
            {
                SetValByKey("CarWidthMin", value);
            }
        }
        public int CarWidthMax
        {
            get
            {
                return GetValIntByKey("CarWidthMax");
            }
            set
            {
                SetValByKey("CarWidthMax", value);
            }
        }


        public int Onhand
        {
            get
            {
                return GetValIntByKey("Onhand");
            }
            set
            {
                SetValByKey("Onhand", value);
            }
        }
        /// <summary>
        /// 推断状态
        /// </summary>
        public int StockState
        {
            get
            {
                return GetValIntByKey("StockState");
            }
            set
            {
                SetValByKey("StockState", value);
            }
        }
        /// <summary>
        /// 最高值
        /// </summary>
        public string DTFrom
        {
            get
            {
                return GetValStringByKey("DTFrom");
            }
        }
        public string DTTo
        {
            get
            {
                return GetValStringByKey("DTTo");
            }
        }
        public int ResultAll
        {
            get
            {
                return GetValIntByKey("ResultAll");
            }
            set
            {
                SetValByKey("ResultAll", value);
            }
        }
        public int ResultDown
        {
            get
            {
                return GetValIntByKey("ResultDown");
            }
            set
            {
                SetValByKey("ResultDown", value);
            }
        }
        public int ResultTop
        {
            get
            {
                return GetValIntByKey("ResultTop");
            }
            set
            {
                SetValByKey("ResultTop", value);
            }
        }
        public decimal ResultWin
        {
            get
            {
                return GetValDecimalByKey("ResultWin");
            }
            set
            {
                SetValByKey("ResultWin", value);
            }
        }
         
        public int NearDays
        {
            get
            {
                return GetValIntByKey("NearDays");
            }
            set
            {
                SetValByKey("NearDays", value);
            }
        }
        public decimal CarWidth
        {
            get
            {
                return GetValDecimalByKey("CarWidth");
            }
            set
            {
                SetValByKey("CarWidth", value);
            }
        }
        #endregion
    }
    /// <summary>
    /// 推断 s
    /// </summary>
    public class Stocks : EntitiesNoName
    {


        #region 构造函数.
        /// <summary>
        /// 推断
        /// </summary>
        public Stocks() { }
        /// <summary>
        /// 得到它的 Entity 
        /// </summary>
        public override Entity GetNewEntity
        {
            get
            {
                return new Stock();
            }
        }
        #endregion 构造函数.

        #region 为了适应自动翻译成java的需要,把实体转换成List.
        /// <summary>
        /// 转化成 java list,C#不能调用.
        /// </summary>
        /// <returns>List</returns>
        public System.Collections.Generic.IList<Stock> ToJavaList()
        {
            return (System.Collections.Generic.IList<Stock>)this;
        }
        /// <summary>
        /// 转化成list
        /// </summary>
        /// <returns>List</returns>
        public System.Collections.Generic.List<Stock> Tolist()
        {
            System.Collections.Generic.List<Stock> list = new System.Collections.Generic.List<Stock>();
            for (int i = 0; i < Count; i++)
            {
                list.Add((Stock)this[i]);
            }
            return list;
        }
        #endregion 为了适应自动翻译成java的需要,把实体转换成List.
    }
}
